package com.lidong.zc.databasemodel.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.lidong.zc.databasemodel.constants.DataBaseTypeConst;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.mapping.VendorDatabaseIdProvider;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.Locale;
import java.util.Properties;

/**
 * Mybatis databaseId 属性的配置
 *
 * @author LiDong
 * @version 1.0.0
 * @createTime 10/1/2022 10:36 AM
 */
@Configuration
public class DataBaseConfig {

    private static final Logger logger = LoggerFactory.getLogger(DataBaseConfig.class);

    /**
     * 数据库类型
     */
    private static String dbType = "default";

    /**
     * Mybatis 目录
     */
    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;

    /**
     * 建表扫描路径
     */
    @Value("${mybatis.model-pack}")
    private String modelPack;

    /**
     * Druid 数据源
     */
    @Autowired
    private DruidDataSource dataSource;

    @Bean
    public DatabaseIdProvider databaseIdProvider() {
        DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
        Properties properties = new Properties();
        String dbType = dataSource.getDbType();
        properties.setProperty(dbType, dbType.toLowerCase(Locale.ROOT));
        properties.setProperty("Oracle", "oracle");
        properties.setProperty("MySQL", "mysql");
        properties.setProperty("PostgreSQL", "postgresql");
        properties.setProperty("DB2", "db2");
        properties.setProperty("SQL Server", "sqlserver");
        databaseIdProvider.setProperties(properties);
        logger.info("Module:lowcode-database:DatabaseIdProvider bean registered!");
        return databaseIdProvider;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setDatabaseIdProvider(this.databaseIdProvider());
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
        logger.info("Module:lowcode-database:SqlSessionFactoryBean bean registered!");
        return factoryBean;
    }

    /**
     * 初始 dbType
     *
     * @param environment          environment
     * @param dataSourceProperties dataSourceProperties
     */
    @Autowired
    private void initJDCInfo(Environment environment, DataSourceProperties dataSourceProperties) {
        String driverName = dataSourceProperties.getDriverClassName();
        String type = environment.getProperty("spring.datasource.dbType", "default");
        if ("default".equalsIgnoreCase(type)) {
            if (driverName.startsWith("com.mysql.")) {
                dbType = DataBaseTypeConst.MYSQL;
            } else if (driverName.contains(".SQLServerDriver")) {
                dbType = DataBaseTypeConst.SQLSERVER;
            } else if (driverName.endsWith(".OracleDriver")) {
                dbType = DataBaseTypeConst.ORACLE;
            } else if (driverName.endsWith(".DmDriver")) {
                dbType = DataBaseTypeConst.DAMENG;
            } else if (driverName.contains(".h2.")) {
                dbType = DataBaseTypeConst.H2;
            } else if (driverName.contains(".derby.")) {
                dbType = DataBaseTypeConst.DERBY;
            } else if (driverName.startsWith("org.sqlite")) {
                dbType = DataBaseTypeConst.SQLITE;
            } else if (driverName.startsWith("org.hsqldb")) {
                dbType = DataBaseTypeConst.HSQL;
            } else if (driverName.startsWith("com.sap.db")) {
                dbType = DataBaseTypeConst.HANA;
            } else if (driverName.startsWith("com.informix") || driverName.startsWith("com.gbase")) {
                dbType = DataBaseTypeConst.INFORMIX;
            } else if (driverName.startsWith("com.oscar")) {
                dbType = DataBaseTypeConst.OSCAR;
            } else if (driverName.startsWith("com.kingbase")) {
                dbType = DataBaseTypeConst.KINGBASE;
            } else if (driverName.startsWith("org.postgresql")) {
                dbType = DataBaseTypeConst.POSTGRESQL;
            } else if (driverName.contains(".polardb.")) {
                dbType = DataBaseTypeConst.POLARDB;
            } else if (driverName.startsWith("com.huawei.gauss")) {
                dbType = DataBaseTypeConst.GAUSS;
            }
        } else {
            dbType = type;
        }
    }

    /**
     * 获取 DbType
     *
     * @return String
     */
    public static String getDbType() {
        return dbType;
    }

    /**
     * 获取 DruidDataSource
     *
     * @return DruidDataSource
     */
    public DruidDataSource getDataSource() {
        return dataSource;
    }

    public String getMapperLocations() {
        return mapperLocations;
    }

    public String getModelPack() {
        return modelPack;
    }
}
